package usedForPage;

import java.util.HashSet;
import java.util.Set;
import usedForPage.MapChar;

public class Distance {

	static int costOfDelete = 5;
	static int costOfSlightDelete = 4, costOfRepeatedCharDelete = 4;
	static int costOfSubstitution = 4;
	static int costOfSameSoundChar = 3;
	static int costOfAdjacentChar = 3;
	static int costOfReplaceWithSpace = 5;

	public static int getLevenshteinDistance(String shorterString, String longerString) {
		shorterString = shorterString.trim();
		longerString = longerString.trim();
		if (shorterString == null || longerString == null) {
			throw new IllegalArgumentException("Strings must not be null");
		}
		int lengthFirstText = shorterString.length();
		int lengthSecondText = longerString.length();
		if (lengthFirstText == 0) {
			return lengthSecondText;
		} else if (lengthSecondText == 0) {
			return lengthFirstText;
		}
		if (lengthFirstText > lengthSecondText) {
			String tmp = shorterString;
			shorterString = longerString;
			longerString = tmp;
			lengthFirstText = lengthSecondText;
			lengthSecondText = longerString.length();
		}
		int p[] = new int[lengthFirstText + 1];
		int d[] = new int[lengthFirstText + 1];
		int tempArray[];
		int firstString;
		int secondString;
		char jthCharacterOfSecondText, beforeJthChar = '!';
		int cost;
		for (firstString = 0; firstString <= lengthFirstText; firstString++) {
			p[firstString] = firstString * costOfDelete;
		}
		for (secondString = 1; secondString <= lengthSecondText; secondString++) {
			jthCharacterOfSecondText = longerString.charAt(secondString - 1);
			d[0] = secondString * costOfDelete;
			for (firstString = 1; firstString <= lengthFirstText; firstString++) {
				if (shorterString.charAt(firstString - 1) == jthCharacterOfSecondText) {
					cost = 0;
				} else {
					cost = checkChar(shorterString.charAt(firstString - 1), jthCharacterOfSecondText);
				}
				int costOfDel = getCostOfDel(jthCharacterOfSecondText, beforeJthChar);
				d[firstString] = Math.min(Math.min(d[firstString - 1] + costOfDel, p[firstString] + costOfDel),
						p[firstString - 1] + cost);
			}
			tempArray = p;
			p = d;
			d = tempArray;
			beforeJthChar = jthCharacterOfSecondText;
		}
		return p[lengthFirstText];
	}

	private static int getCostOfDel(char ch, char previousChar) {
		Set<Character> stChar = new HashSet<Character>();
		stChar.add('a');
		stChar.add('e');
		stChar.add('i');
		stChar.add('o');
		stChar.add('u');
		int cost;
		if (stChar.contains(ch)) {
			cost = costOfSlightDelete;
		} else {
			if (ch == previousChar) {
				cost = costOfRepeatedCharDelete;
			} else {
				cost = costOfDelete;
			}
		}
		return cost;
	}

	private static int checkChar(char first, char second) {
		int diff = costOfSubstitution;
		if (MapChar.getHmCharStSameSound().containsKey(first)) {
			if (MapChar.getHmCharStSameSound().get(first).contains(second))
				diff = costOfSameSoundChar;
		} else {
			if (MapChar.getHmCharStAdjacent().containsKey(first)) {
				if (MapChar.getHmCharStAdjacent().get(first).contains(second))
					diff = costOfAdjacentChar;
			}
		}
		if (first == ' ' || second == ' ')
			diff = costOfReplaceWithSpace;
		return diff;
	}

	public static double getDistanceForProviders(String searchedName, String secondProviderName) {
		double minDis = 0, temDis, totalDis;
		try {
			searchedName = editName(searchedName, 1);
			secondProviderName = editName(secondProviderName, 1);
			String testedName;
			minDis = 1000;
			int l1 = searchedName.length(), l2 = secondProviderName.length(), l3 = l2 - l1;
			if (l1 <= l2) {
				for (int i = 0; i <= l3; i++) {
					testedName = secondProviderName.substring(i, i + l1);
					temDis = Distance.getLevenshteinDistance(searchedName, testedName);
					if (searchedName.charAt(0) != secondProviderName.charAt(0))
						if(secondProviderName.indexOf(" "+searchedName)==-1)
						temDis += 2;
					if ((searchedName.indexOf(" ") == -1 && testedName.indexOf(" ") != -1)
							|| (searchedName.indexOf(" ") != -1 && testedName.indexOf(" ") == -1))
						temDis += 2;
					if (temDis < minDis)
						minDis = temDis;
				}
			} else {
				temDis = Distance.getLevenshteinDistance(searchedName, secondProviderName);
				if (searchedName.charAt(0) != secondProviderName.charAt(0))
					temDis += 2;
				if ((searchedName.indexOf(" ") == -1 && secondProviderName.indexOf(" ") != -1)
						|| (searchedName.indexOf(" ") != -1 && secondProviderName.indexOf(" ") == -1))
					temDis += 2;
				if (temDis < minDis)
					minDis = temDis;
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		totalDis = minDis;
		return totalDis;
	}

	private static String editName(String name, int lenght) {
		name = name.toLowerCase();
		name = name.replaceAll("\\bdr\\b", "");
		name = name.replaceAll("\\bdr.\\b", "");
		name = name.replaceAll("\\bmd\\b", "");
		name = name.replaceAll("\\bfnp\\b", "");
		name = name.replaceAll("\\bnp\\b", "");
		name = name.replaceAll("\\bdpt\\b", "");
		name = name.replaceAll("\\bnpt\\b", "");
		name = name.replaceAll("\\bphd\\b", "");
		name = name.replaceAll("\\bdo\\b", "");
		name = name.replaceAll("\\bcrna\\b", "");
		name = name.replaceAll("\\bbsn\\b", "");
		name = name.replaceAll("\\bms\\b", "");
		name = name.replaceAll("\\brd\\b", "");
		name = name.replaceAll("\\bcd\\b", "");
		name = name.replaceAll("\\blat\\b", "");
		name = name.replaceAll("\\batc\\b", "");
		name = name.replaceAll("\\bpa-c\\b", "");
		String res = "";
		String[] tem = name.split(" ");
		for (int i = 0; i < tem.length; i++) {
			if (tem[i].length() > lenght)
				res = res + " " + tem[i];
		}
		return res.trim().toLowerCase();
	}
}
